package login

import (
	"context"
	"time"

	"server_1.0/api/internal/svc"
	"server_1.0/api/internal/types"
	"server_1.0/service/admin/admin"
	"server_1.0/service/student/student"
	"server_1.0/util"

	"github.com/golang-jwt/jwt"
	"github.com/zeromicro/go-zero/core/logx"
)

type LoginLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic {
	return &LoginLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *LoginLogic) Login(req *types.LoginRep) (resp *types.PostReps, err error) {
	code := util.Success
	Msg := "成功"
	Token := ""
	No := ""
	Name := ""
	accessExpire := l.svcCtx.Config.JwtAuth.AccessExpire
	now := time.Now().Unix()
	if len(req.UserName) > 8 {
		Reps, _ := l.svcCtx.StudentRpc.QueryID(l.ctx, &student.QueryIDReq{
			No: req.UserName,
		})
		sig := Reps.QRs[0]
		if sig.Code == 503 {
			code = util.NoFoundError
			Msg = "账号错误"
		} else {
			if req.Password != sig.Password {
				code = util.NoFoundError
				Msg = "密码错误"
			} else {
				jwtToken, err := l.getJwtToken(l.svcCtx.Config.JwtAuth.AccessSecret, now, accessExpire, sig.No)
				if err != nil {
					return nil, util.NewCodeError(util.Error, "失败")
				}
				l.svcCtx.Redis.Set("loginUserId:"+sig.No, sig.Name+";", time.Duration(accessExpire)*time.Second)
				l.svcCtx.Redis.Do("SADD", "loginStatus", sig.No)
				Token = jwtToken
				No = sig.No
				Name = sig.Name
			}
		}
	} else {
		reps, _ := l.svcCtx.AdminRpc.Query(l.ctx, &admin.QueryReq{
			No: req.UserName,
		})
		sig := reps.QRs[0]
		if sig.Code == 503 {
			code = util.NoFoundError
			Msg = "账号错误"
		} else {
			if req.Password != sig.Password {
				code = util.PasswordError
				Msg = "密码错误"
			} else {
				jwtToken, err := l.getJwtToken(l.svcCtx.Config.JwtAuth.AccessSecret, now, accessExpire, sig.No)
				if err != nil {
					return nil, util.NewCodeError(util.Error, "失败")
				}
				l.svcCtx.Redis.Set("loginUserId:"+sig.No, sig.No+";", time.Duration(accessExpire)*time.Second)
				l.svcCtx.Redis.Do("SADD", "loginStatus", sig.No)
				Token = jwtToken
				No = sig.No
				Name = "admin"
			}
		}
	}
	return &types.PostReps{
		Code: code,
		Msg:  Msg,
		Data: map[string]interface{}{
			"No":          No,
			"Name":        Name,
			"Token":       Token,
			"ExprieTime":  now + accessExpire,
			"RefreshTime": now + accessExpire/2,
		},
	}, nil
}

func (l *LoginLogic) getJwtToken(secretKey string, iat, seconds int64, userId string) (string, error) {
	claims := make(jwt.MapClaims)
	claims["exp"] = iat + seconds
	claims["iat"] = iat
	claims["userId"] = userId
	token := jwt.New(jwt.SigningMethodHS256)
	token.Claims = claims
	return token.SignedString([]byte(secretKey))
}
